<!doctype html>
<html lang="en-US">
  <head>
    <title>Web Chat: Save and restore scroll position (comprehensive)</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!--
      For simplicity and code clarity, we are using Babel and React from unpkg.com.
    -->
    <script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone@7.8.7/babel.min.js"></script>
    <script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.development.js"></script>
    <script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.development.js"></script>
    <!--
      This CDN points to the latest official release of Web Chat. If you need to test against Web Chat's latest bits, please refer to using Web Chat's latest bits:
      https://github.com/microsoft/BotFramework-WebChat#how-to-test-with-web-chats-latest-bits
    -->
    <script crossorigin="anonymous" src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    <style>
      html,
      body {
        height: 100%;
      }

      body {
        margin: 0;
      }

      #webchat {
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
        height: 100%;
        margin: auto;
        max-width: 480px;
        min-width: 360px;
      }

      .button-overlay {
        background-color: White;
        border-color: #393;
        border-radius: 4px;
        border-style: solid;
        border-width: 2px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
        display: flex;
        flex-direction: column;
        left: 10px;
        padding: 5px;
        position: absolute;
        top: 10px;
      }

      .button-overlay__button {
        margin: 5px;
      }

      .button-overlay__saved-position {
        margin: 5px;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="webchat"></div>
    <script type="text/babel" data-presets="env,stage-3,react">
      (async function () {
        const {
          React: { useCallback, useEffect, useRef, useState },
          WebChat: {
            Components: { BasicWebChat, Composer },
            createDirectLine,
            hooks: { useConnectivityStatus, useObserveScrollPosition, useScrollTo, useScrollToEnd, useSendMessage }
          }
        } = window;

        // In this demo, we are using Direct Line token from MockBot.
        // Your client code must provide either a secret or a token to talk to your bot.
        // Tokens are more secure. To learn about the differences between secrets and tokens
        // and to understand the risks associated with using secrets, visit https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication?view=azure-bot-service-4.0

        const res = await fetch(
          'https://hawo-mockbot4-token-app.blueriver-ce85e8f0.westus.azurecontainerapps.io/api/token/directline',
          { method: 'POST' }
        );
        const { token } = await res.json();

        const ButtonOverlay = () => {
          const [behavior, setBehavior] = useState('smooth');
          const [savedScrollPosition, setSavedScrollPosition] = useState();
          const scrollPositionRef = useRef();
          const scrollTo = useScrollTo();
          const scrollToEnd = useScrollToEnd();

          useObserveScrollPosition(
            position => {
              scrollPositionRef.current = position;
            },
            [scrollPositionRef]
          );

          const handleBehaviorChange = useCallback(
            ({ target: { checked } }) => {
              setBehavior(checked ? 'smooth' : 'auto');
            },
            [setBehavior]
          );

          const handleSavePositionClick = useCallback(
            () => setSavedScrollPosition(scrollPositionRef.current),
            [scrollPositionRef, setSavedScrollPosition]
          );

          const handleScrollTo100PixelClick = useCallback(
            () => scrollTo({ scrollTop: 100 }, { behavior }),
            [behavior, scrollTo]
          );

          const handleScrollToEndClick = useCallback(
            () => scrollTo({ scrollTop: '100%' }, { behavior }),
            [behavior, scrollToEnd]
          );

          const handleScrollToSavedActivityClick = useCallback(
            () => scrollTo({ activityID: savedScrollPosition.activityID }, { behavior }),
            [behavior, savedScrollPosition, scrollTo]
          );

          const handleScrollToSavedPositionClick = useCallback(
            () => scrollTo({ scrollTop: savedScrollPosition.scrollTop }, { behavior }),
            [behavior, savedScrollPosition, scrollTo]
          );

          return (
            <div className="button-overlay">
              <label>
                <input checked={behavior === 'smooth'} onChange={handleBehaviorChange} type="checkbox" />
                Smooth scrolling
              </label>
              <button className="button-overlay__button" onClick={handleSavePositionClick} type="button">
                Save current position
              </button>
              <button
                className="button-overlay__button"
                disabled={!savedScrollPosition}
                onClick={handleScrollToSavedActivityClick}
                type="button"
              >
                {behavior === 'smooth' ? 'Scroll to saved activity' : 'Jump to saved activity'}
              </button>
              <button
                className="button-overlay__button"
                disabled={!savedScrollPosition}
                onClick={handleScrollToSavedPositionClick}
                type="button"
              >
                {behavior === 'smooth' ? 'Scroll to saved position' : 'Jump to saved position'}
              </button>
              <button className="button-overlay__button" onClick={handleScrollTo100PixelClick} type="button">
                {behavior === 'smooth' ? 'Scroll to 100px' : 'Jump to 100px'}
              </button>
              <button className="button-overlay__button" onClick={handleScrollToEndClick} type="button">
                {behavior === 'smooth' ? 'Scroll to end' : 'Jump to end'}
              </button>
              {savedScrollPosition && (
                <pre className="button-overlay__saved-position">{JSON.stringify(savedScrollPosition, null, 2)}</pre>
              )}
            </div>
          );
        };

        const SendHelpOnConnect = () => {
          const [connectivityStatus] = useConnectivityStatus();
          const sendMessage = useSendMessage();

          useEffect(() => {
            connectivityStatus === 'connected' && sendMessage('help');
          }, [connectivityStatus, sendMessage]);

          return false;
        };

        ReactDOM.render(
          <Composer directLine={createDirectLine({ token })}>
            <BasicWebChat />
            <ButtonOverlay />
            <SendHelpOnConnect />
          </Composer>,
          document.getElementById('webchat')
        );
      })().catch(err => console.error(err));
    </script>
  </body>
</html>
